﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using eProject.Model;

namespace eProject.Logic
{
    public class Tasks //TODO Serializable?
    {
        public Activities Activities { get; private set; }

        public Tasks()
        {
            SetActivities(new Activities());
        }        

        private readonly Dictionary<Task, double> _tasks = new Dictionary<Task, double>();

        public long Count { get { return _tasks.Count; } }

        public delegate void TaskEventHandler(Task task);

        public event TaskEventHandler TaskAdded;

        private void InvokeTaskAdded(Task task)
        {
            var handler = TaskAdded;
            if (handler != null) handler(task);
        }

        public event TaskEventHandler TaskRemoved;

        private void InvokeTaskRemoved(Task task)
        {
            var removed = TaskRemoved;
            if (removed != null) removed(task);
        }

        public event TaskEventHandler TaskChanged;

        private void InvokeTaskChanged(Task task)
        {
            var changed = TaskChanged;
            if (changed != null) changed(task);
        }

        private void SetActivities(Activities activities)
        {
            //TODO replace this method
            Activities = activities;
            Activities.ActivityAdded += ActivityEventHandler;
            Activities.ActivityRemoved += ActivityEventHandler;
            Activities.ActivityChanged += ActivityEventHandler;
            Activities.ManHoursChanged += ManHoursChangedEventHandler;
        }

        public void AddTask(Task task)
        {
            if (task == null)
            {
                throw new ArgumentNullException("task");
            }
            _tasks.Add(task,0);
            RecalculateTask(task);
            task.TaskChanged += TaskChangedEventHandler;
            InvokeTaskAdded(task);
        }

        public void RemoveTask(Task task)
        {
            if (task == null)
            {
                throw new ArgumentNullException("task");
            }
            _tasks.Remove(task);
            task.TaskChanged -= TaskChangedEventHandler;
            InvokeTaskRemoved(task);
        }   
     
        public IEnumerable<Task> Items
        {
            get { return _tasks.Keys; }
        }     
  
        public double GetManHours(Task task)
        {//TODO checking
            return _tasks[task];
        }

        private void RecalculateTask(Task task)
        {
            var acts = Activities.GetActivities(task);
            var manHours = acts.Sum(a => Activities.GetManHours(a));
            _tasks[task] = manHours;
        }

        private void ActivityEventHandler(Activity activity)
        {
            RecalculateTask(activity.Task);
        }

        private void ManHoursChangedEventHandler(IEnumerable<Activity> activities)
        {
            var tasks = (from act in activities
                       select act.Task).Distinct();
            foreach (var task in tasks)
            {
                RecalculateTask(task);
            }
        }

        private void TaskChangedEventHandler(Task task)
        {
            InvokeTaskChanged(task);
        }
        
    }
}
